Freeware assember ASxx.EXE Ver 1.03. 0001 ;************************************************************* 0002 ; 0003 ; ADAMnet Hard Disk controller code for IDE hard disk 0004 ; drive on Micro Innovations ADAMnet IDE controller. 0005 ; 0006 ; ADAMnet I/O code is from DBL4.ASM program by Tony 0007 ; Morehen and Guy Cousineau. Hard disk I/O code is 0008 ; original work by Mark Gordon of Micro Innovations. 0009 ; 0010 ; Creation date: June 22, 1995 0011 ; Authors: As described above 0012 ; Copyright: AJM Software (ADAMnet code) and 0013 ; Micro Innovations (Disk I/O code) 0014 ; Revision: Original 0015 ; 0016 ;************************************************************* 0017 0018 0004 DRVNO EQU 4 ;Set drive address to 4 0019 0020 ; 0021 ; Hard Disk register addresses 0022 ; 0023 0024 1800 WRRESET EQU 1800H ;Write causes a pulse on HD's RESET line 0025 0801 RDERROR EQU 0801H ;Error register (Read) 0026 1801 WRPRECP EQU 1801H ;Write Precompenstion register (Write) 0027 0802 RDSECCT EQU 0802H ;Sector Count register (Read) 0028 1802 WRSECCT EQU 1802H ;Sector Count register (Write) 0029 0803 RDSECNO EQU 0803H ;Sector Number register (Read) 0030 1803 WRSECNO EQU 1803H ;Sector Number register (Write) 0031 0804 RDCYLLO EQU 0804H ;Cylinder register low byte (Read) 0032 1804 WRCYLLO EQU 1804H ;Cylinder register low byte (Write) 0033 0805 RDCYLHI EQU 0805H ;Cylinder register high byte (Read) 0034 1805 WRCYLHI EQU 1805H ;Cylinder register High byte (Write) 0035 0806 RDSDH EQU 0806H ;Size, Drive, Head register (Read) 0036 1806 WRSDH EQU 1806H ;Size, Drive, Head register (Write) 0037 0807 RDSTAT EQU 0807H ;Status register (Read) 0038 1807 WRCMD EQU 1807H ;Command register (Write) 0039 0808 RDDATLO EQU 0808H ;Data register low byte (Read) 0040 1808 WRDATLO EQU 1808H ;Data register low byte (Write) 0041 0809 RDDATHI EQU 0809H ;Data register high byte (Read) 0042 1809 WRDATHI EQU 1809H ;Data register high byte (Write) 0043 180e WRCONT EQU 180EH ;Fixed Disk Control register (Write) 0044 0045 ; 0046 ; Hard Disk Controller commands 0047 ; 0048 0049 0010 HRECAL EQU 10H ;Home heads to Cylinder 0 0050 0020 HREAD EQU 20H ;Read sector(s) from drive 0051 0030 HWRITE EQU 30H ;Write sector(s) to drive 0052 0040 HREADV EQU 40H ;Read verify sector(s) 0053 0050 HFORMAT EQU 50H ;Format track 0054 0070 HSEEK EQU 70H ;Seek cylinder 0055 0090 HDIAG EQU 90H ;Perform self test & report 0056 0091 HSTPARM EQU 91H ;Set drive parameters 0057 0092 HSCANID EQU 92H ;Get current head position 0058 00ec HIDDRV EQU 0ECH ;Identify drive 0059 0004 HRESET EQU 4 ;Sent to control register to reset drive 0060 0002 HNOIRQ EQU 2 ;Sent to control register to disable interrupt 0061 0062 ; 0063 ; 680X Internal RAM locations 0064 ; 0065 0066 0000 P1DDR EQU 00H ;port 1 data direction register 0067 0001 P2DDR EQU 01H ;port 2 data direction register 0068 0002 P1DATA EQU 02H ;port 1 data register 0069 0003 P2DATA EQU 03H ;port 2 data register 0070 0005 P4DDR EQU 05H ;port 4 data direction register 0071 0008 TCSR EQU 08H ;timer control and status register 0072 0009 COUNTER EQU 09H ;counter register 0073 000b OUTCMP EQU 0BH ;output compare register 0074 0010 RMCR EQU 10H ;SCI rate and mode control register 0075 0011 SCICSR EQU 11H ;SCI Tx/Rx control and status register 0076 0012 SCIRXD EQU 12H ;SCI Rx data register 0077 0013 SCITXD EQU 13H ;SCI Tx data register 0078 0014 RAMCR EQU 14H ;RAM control register 0079 0080 ; 0081 ; 680X internal RAM storage definitions 0082 ; (SP gets set at 00EC - What is ED thru FF used for?) 0083 ; 0084 0085 0080 ORG 80H 0086 0087 0080 CURMSG DS 5 ;command message buffer (send/rcv instructions ) 0088 0085 LSTMSG DS 5 ;last command buffer 0089 008a STRLEN DS 2 ;message length 0090 008c BLKLOC DS 2 ;where in memory to get/save message 0091 008e CHKSUM DS 1 ;calculated checksum 0092 008f MSTAT DS 4 ;status message buffer 0093 ; 0094 ; Primary, Secondary and combined device status codes: 0095 ; 01 = No error 04 = Missing Media error 0096 ; 02 = CRC error 05 = Missing Drive error 0097 ; 03 = Missing Block error 06 = Write Protect error 0098 ; 0099 0093 CSTAT DS 1 ;combined status (PSTAT in lower 0100 ; nibble, SSTAT in upper nibble) 0101 0094 PSTAT DS 1 ;primary status 0102 0095 SSTAT DS 1 ;secondary status 0103 ; 0104 0096 L0096 DS 2 ;Purpose Unknown 0105 0098 DEVNUM DS 1 ;device node ID 0106 0099 CMDSTG DS 5 ;command stage for multi-byte commands 0107 009e DATREQ DS 1 ;data requested flag 0108 009f RDWRT DS 1 ;read(=0BH)/write(=0CH) flag 0109 00a0 THREEB DS 1 ;three byte block number flag 0110 00a1 HSPT DS 2 ;number of host sectors/track (2 Bytes) 0111 00a3 HNHSPT DS 2 ;no of host HDS * SPT (two bytes) 0112 00a5 REQHD DS 1 ;requested head number 0113 00a6 REQSEC DS 1 ;requested sector number 0114 00a7 REQCYL DS 2 ;requested cylinder number (2 bytes) 0115 0116 ; I/O buffer addresses (same memory addressed 0117 ; at 1400H for read and 0400H for write) 0118 0119 0400 BLKWRT EQU 400H ;write to external memory 0120 1400 BLKRD EQU 1400H ;read from external memory 0121 0122 ; Hard drive configuration data 0123 ; (Valid only when buffer contains block 0) 0124 0125 1403 PTRACK EQU BLKRD+3 ;No of HD cylinders 0126 1405 PSEEK EQU BLKRD+5 ;No of HD heads 0127 1406 PSPT EQU BLKRD+6 ;No of HD sec/track 0128 1407 PNHSPT EQU BLKRD+7 ;Product of SPT and heads 0129 1408 PPRECMP EQU BLKRD+8 ;HD Precomp value (SASI only) 0130 1409 PMAXDR EQU BLKRD+9 ;No of EOS partitions? 0131 140a PDRVSZ EQU BLKRD+10 ;Size of each EOS partition? 0132 1414 POFFSET EQU BLKRD+20 ;Offset to each HD partition? 0133 142b PCPM EQU BLKRD+43 ;Start of CPM Track Offset 0134 0135 ; 0136 ; AdamNet Messages where N = Node ID 0137 ; 0N - reset node 0138 ; 1N - request status 0139 ; 3N - clear 0140 ; 4N - receive 0141 ; 6N - send 0142 ; 0DN - ready 0143 ; 0144 ; The disk drive code comprises two separate devices, the net handler 0145 ; and the disk handler. The net handler is only triggered when the 6803 0146 ; receives a byte over AdamNet. It interprets the AdamNet command, acts 0147 ; on the command (including sending and receiving blocks of data over the 0148 ; Net) and sets the appropriate flags and data blocks in memory. The 0149 ; disk handler is normally in control of the drive. It initializes the 0150 ; various flags and hardware and then loops, monitoring the data request 0151 ; flag. When it finds a data request, it reads or writes to the disk 0152 ; drive, depending upon the read/write flag. If the disk handler gets 0153 ; a request to write to block FACEH, it does a format. 0154 ; 0155 ;AdamNet procedure to write to disk: 0156 ; 1) Master node uses send command to send block specifications to disk drive. 0157 ; Block spec. is 5 bytes, 4 bytes block number (LSB ... MSB) and one byte 0158 ; device spec (0 = primary device, NZ = secondary device). The net 0159 ; handler puts all blocks less than 400H in message buffer. Blocks of 0160 ; 400H go in external memory. 0161 ; 2) Master node uses send command to send data block to disk. 0162 ; 3) Net handler sets data request and write flags and returns to disk 0163 ; handler. 0164 ; 4) Disk handler sees flags, reads the block specification and writes 0165 ; external memory to disk. 0166 ; 0167 ;AdamNet procedure to read from disk: 0168 ; 1) Master node uses send command to send block specifications to disk drive. 0169 ; 2) Master node uses receive command to tell disk drive to send data block. 0170 ; 3) Net handler sets data request and read flags and returns to disk 0171 ; handler. 0172 ; 4) Disk handler sees flags, reads the block specification and reads data 0173 ; from disk to external memory. 0174 ; 5) Meanwhile master node queries drive with RDY command. 0175 ; 6) Drive ACKs ready when disk handler has comleted task. 0176 ; 7) Master node then uses CLEAR command to tell net handler to send data. 0177 ; 8) Net handler now sends data in external memory 0178 ; 0179 0180 ; Code starts halfway through PROM - first half unused 0181 0182 f800 ORG 0F800H 0183 0184 f800 17 TBA ;unused 0185 SCIINT: 0186 f801 7d 00 9e TST DATREQ ;is there an active data request 0187 f804 26 26 BNE SCINT3 ;if none, finish up, ignoring Net 0188 f806 bd f9 f3 JSR RDSCI ;read byte from SCI 0189 f809 25 2b BCS SCINT4 ;jump if good read (and good net address) 0190 f80b 28 1f BVC SCINT3 ;if address bad, finish up, ignoring Net 0191 ;must be bad read, so NACK it 0192 f80d 86 02 LDAA #$2 ;enable Tx interrupt 0193 f80f 97 11 STAA SCICSR 0194 SCINT1: 0195 f811 ce 00 0e LDX #$0E ;set wait count 0196 f814 86 08 LDAA #$8 ;get ready to test bit 3 0197 SCINT2: 0198 f816 95 03 BITA P2DATA ;is bit 3 of port 2 data set by SCI 0199 f818 27 f7 BEQ SCINT1 ;no, loop until it's set 0200 f81a 09 DEX ;make sure it stays set long enough 0201 f81b 26 f9 BNE SCINT2 ;by looping until IX = 0 0202 f81d 86 1b LDAA #$1B ;enable Rx, RxI, Wakeup 0203 f81f 97 11 STAA SCICSR 0204 f821 7d 00 99 TST CMDSTG ;are we in the middle of a command 0205 f824 27 06 BEQ SCINT3 ;no, just reset SCI 0206 f826 4f CLRA ;clear command stage flag 0207 f827 97 99 STAA CMDSTG 0208 f829 7e f8 92 JMP NACK ;send NACK 0209 SCINT3: 0210 f82c c6 1b LDAB #$1B ;enable Rx, RxI, Wakeup 0211 f82e d7 11 STAB SCICSR 0212 f830 4f CLRA ;clear command stage flag 0213 f831 97 99 STAA CMDSTG 0214 f833 7e f9 d2 JMP SCIEND ;reset SCI 0215 SCINT4: 0216 f836 d6 99 LDAB CMDSTG ;get the command stage flag in B 0217 f838 58 ASLB ;multiply by 2 0218 f839 ce f8 41 LDX #TBL1 ;point to command jump table 0219 f83c 3a ABX ;add offset in B 0220 f83d ee 00 LDX $0,X ;get address from table 0221 JMPIX: 0222 f83f 6e 00 JMP $0,X ;jump to address 0223 TBL1: 0224 f841 f8 4d DW STAGE0 0225 f843 f9 28 DW STAGE1 0226 f845 f9 31 DW STAGE2 0227 f847 f9 56 DW STAGE3 0228 f849 f9 5d DW STAGE4 0229 f84b f9 77 DW STAGE5 0230 STAGE0: 0231 f84d 84 f0 ANDA #$0F0 ;mask off lower nibble 0232 f84f 81 00 CMPA #$0 ;is it NetReset 0233 f851 26 07 BNE NOTRST ;no, check other commands 0234 f853 0d SEC ;set carry 0235 f854 bd fa 54 JSR SETREQ 0236 f857 7e f9 d2 JMP SCIEND ;reset SCI 0237 NOTRST: 0238 f85a 81 10 CMPA #$10 ;is it status request? 0239 f85c 27 5c BEQ STATUS ;yes, jump 0240 f85e 81 30 CMPA #$30 ;is it clear 0241 f860 26 03 BNE NOTCLR ;no, jump 0242 f862 7e f8 e6 JMP CLEAR 0243 NOTCLR: 0244 f865 81 40 CMPA #$40 ;is it Rx 0245 f867 26 17 BNE NOTRX ;no, jump 0246 f869 ce 00 05 LDX #$5 ;counter to test 5 bytes 0247 RX1: 0248 f86c a6 7f LDAA $7F,X ;compare location 7F+X 0249 f86e a1 84 CMPA $84,X ;to location 84+X 0250 f870 26 05 BNE RX2 ;jump if different 0251 f872 09 DEX ;check counter 0252 f873 26 f7 BNE RX1 ;loop if more bytes to check 0253 f875 20 2f BRA ACK ;all the same to send ACK 0254 RX2: 0255 f877 86 0b LDAA #$0B 0256 f879 0c CLC 0257 f87a bd fa 54 JSR SETREQ 0258 f87d 7e f9 d2 JMP SCIEND 0259 NOTRX: 0260 f880 81 60 CMPA #$60 ;is it send 0261 f882 26 07 BNE NOTSND ;no, jump 0262 f884 86 01 LDAA #$1 ;now stage 0 0263 f886 97 99 STAA CMDSTG ;so set it 0264 f888 7e f9 d2 JMP SCIEND ;reset SCi 0265 NOTSND: 0266 f88b 81 d0 CMPA #$0D0 ;is it RDY 0267 f88d 27 17 BEQ ACK ;yes, send ACK 0268 f88f 7e f9 d2 JMP SCIEND ;else reset SCI (ignore command) 0269 NACK: 0270 f892 86 c0 LDAA #$0C0 ;NACK in upper nibble of A 0271 f894 9a 98 ORAA DEVNUM ;node ID in lower nibble of A 0272 f896 bd fa 11 JSR TXBYTE ;send it 0273 f899 25 08 BCS NACK1 ;if bad send 0274 f89b bd fa 29 JSR RXBYTE ;get response 0275 f89e 25 03 BCS NACK1 ;if bad receive 0276 f8a0 7e f9 d2 JMP SCIEND ;reset SCI 0277 NACK1: 0278 f8a3 7e f9 e2 JMP SCIND1 ;return from interrupt 0279 ACK: 0280 f8a6 86 90 LDAA #$90 ;ACK in upper nibble of A 0281 f8a8 9a 98 ORAA DEVNUM ;node ID in lower nibble 0282 f8aa bd fa 11 JSR TXBYTE ;send it 0283 f8ad 25 08 BCS ACK1 ;if bad send 0284 f8af bd fa 29 JSR RXBYTE ;get response 0285 f8b2 25 03 BCS ACK1 ;if bad receive 0286 f8b4 7e f9 d2 JMP SCIEND ;reset SCI 0287 ACK1: 0288 f8b7 7e f9 e2 JMP SCIND1 ;return from interrupt 0289 STATUS: 0290 f8ba fc f9 ee LDD TBL2 ;load double accumulator with 8000H 0291 ;(status + MSB of msg len) 0292 f8bd 9a 98 ORAA DEVNUM ;put device number in lower nibble of A (=80) 0293 f8bf dd 8f STD MSTAT ;save in buffer for status message 0294 f8c1 fc f9 f0 LDD TBL3 ;load double accumulator with 401H 0295 f8c4 dd 91 STD MSTAT+2 ;put in 91 and 92 0296 f8c6 bd f9 e3 JSR GETSTAT ;put double stat in 93 0297 f8c9 ce 00 8f LDX #MSTAT ;point to string to send 0298 f8cc cc 00 05 LDD #$5 ;load double accumulator with string length 0299 f8cf dd 8a STD STRLEN ;save string length 0300 f8d1 86 80 LDAA #$80 ;initialize checksum 0301 f8d3 9a 98 ORAA DEVNUM 0302 f8d5 97 8e STAA CHKSUM 0303 f8d7 bd f9 b2 JSR TXSTR ;send response 0304 f8da 25 07 BCS STAT1 ;if error 0305 f8dc 86 01 LDAA #$1 0306 f8de 97 96 STAA L0096 ;put 1 if ???? flag - not used anywhere else 0307 f8e0 7e f9 d2 JMP SCIEND ;reset SCI 0308 STAT1: 0309 f8e3 7e f9 e2 JMP SCIND1 ;jump to RTI 0310 CLEAR: 0311 f8e6 7d 00 84 TST CURMSG+4 ;was the last command for primary device 0312 f8e9 27 04 BEQ CLR1 ;yes, skip next 0313 f8eb 96 95 LDAA SSTAT ;so load secondary device status 0314 f8ed 20 02 BRA CLR2 ;skip next 0315 CLR1: 0316 f8ef 96 94 LDAA PSTAT ;get primary device status 0317 CLR2: 0318 f8f1 81 03 CMPA #$3 ;test status 0319 f8f3 24 0a BCC CLR3 ;if 3 or greater, jump 0320 f8f5 ce 14 00 LDX #BLKRD ;get ready to read external memory 0321 f8f8 cc 04 00 LDD #$0400 ;400H to send 0322 f8fb dd 8a STD STRLEN ;so set message length 0323 f8fd 20 0b BRA CLR4 ;skip next 0324 CLR3: 0325 f8ff bd f9 e3 JSR GETSTAT ;put combined status message in CSTAT 0326 f902 ce 00 93 LDX #CSTAT ;point to CSTAT 0327 f905 cc 00 01 LDD #$1 ;message length = 1 0328 f908 dd 8a STD STRLEN 0329 CLR4: 0330 f90a bd f9 98 JSR SNDMSG ;send message (Block or error) 0331 f90d 25 16 BCS CLR8 ;if error 0332 f90f 7d 00 84 TST CURMSG+4 ;was last for primary device 0333 f912 27 04 BEQ CLR5 ;yes, skip next 0334 f914 96 95 LDAA SSTAT ;get secondary status 0335 f916 20 02 BRA CLR6 ;skip next 0336 CLR5: 0337 f918 96 94 LDAA PSTAT ;get primary status 0338 CLR6: 0339 f91a 81 01 CMPA #$1 ;test status 0340 f91c 26 04 BNE CLR7 ;if not 1, jump 0341 f91e 86 ff LDAA #$0FF ;set external memory contents bad 0342 f920 97 89 STAA LSTMSG+4 0343 CLR7: 0344 f922 7e f9 d2 JMP SCIEND ;exit 0345 CLR8: 0346 f925 7e f9 e2 JMP SCIND1 ;do simple RTI 0347 STAGE1: 0348 ;A = MSB of message length 0349 f928 97 8a STAA STRLEN ;save MSB of message length 0350 f92a 86 02 LDAA #$2 ;activate stage 2 0351 f92c 97 99 STAA CMDSTG 0352 f92e 7e f9 d2 JMP SCIEND ;reset SCI 0353 STAGE2: 0354 ;A = LSB of message length 0355 f931 97 8b STAA STRLEN+1 ;save LSB of message length 0356 f933 81 05 CMPA #$5 ;is it 5? 0357 f935 26 04 BNE STAG21 ;no, it must be 400H 0358 f937 96 8a LDAA STRLEN ;get MSB of message length 0359 f939 27 0c BEQ STAG22 ;if it's 0, ie 0005, jump 0360 STAG21: 0361 f93b 86 03 LDAA #$3 ;activate stage 3 0362 f93d 97 99 STAA CMDSTG 0363 f93f cc 04 00 LDD #BLKWRT ;block to go at 400H 0364 f942 dd 8c STD BLKLOC 0365 f944 7e f9 d2 JMP SCIEND ;reset SCI 0366 STAG22: 0367 f947 86 04 LDAA #$4 ;activate stage 4 0368 f949 97 99 STAA CMDSTG 0369 f94b cc 00 80 LDD #$80 ;block to go at 80H 0370 f94e dd 8c STD BLKLOC 0371 f950 7f 00 8e CLR CHKSUM ;clear the checksum 0372 f953 7e f9 d2 JMP SCIEND ;reset SCI 0373 STAGE3: 0374 ;A = first byte of message 0375 f956 c6 04 LDAB #$4 ;activate stage 4 0376 f958 d7 99 STAB CMDSTG 0377 f95a 7f 00 8e CLR CHKSUM ;clear checksum 0378 STAGE4: 0379 ;A = message byte 0380 f95d de 8c LDX BLKLOC ;get memory location to save message 0381 f95f a7 00 STAA $0,X ;save there 0382 f961 08 INX ;increment pointer 0383 f962 df 8c STX BLKLOC ;save it 0384 f964 98 8e EORA CHKSUM ;calculate checksum 0385 f966 97 8e STAA CHKSUM ;save it 0386 f968 dc 8a LDD STRLEN ;get message length 0387 f96a 83 00 01 SUBD #$1 ;decrement it 0388 f96d dd 8a STD STRLEN ;save it 0389 f96f 26 61 BNE SCIEND ;reset SCI if not done 0390 f971 86 05 LDAA #$5 ;else activate stage 5 0391 f973 97 99 STAA CMDSTG 0392 f975 20 5b BRA SCIEND ;and reset SCI 0393 STAGE5: 0394 ;A = message checksum 0395 f977 c6 00 LDAB #$0 ;reset commmand stage to 0 0396 f979 d7 99 STAB CMDSTG 0397 f97b 91 8e CMPA CHKSUM ;check against calculated checksum 0398 f97d 27 07 BEQ STAG51 ;if they're the same jump 0399 f97f 86 02 LDAA #$2 ;else set primary status to 2 0400 f981 97 94 STAA PSTAT 0401 f983 7e f8 92 JMP NACK ;and send NACK 0402 STAG51: 0403 f986 de 8c LDX BLKLOC ;check if loaded at 80H or 400H 0404 f988 8c 01 00 CPX #$0100 0405 f98b 25 08 BCS STAG52 ;carry set if 80H, so just send ACK 0406 f98d 86 0c LDAA #$0C ;set data write 0407 f98f 97 9f STAA RDWRT 0408 f991 86 aa LDAA #$0AA ;data request flag 0409 f993 97 9e STAA DATREQ 0410 STAG52: 0411 f995 7e f8 a6 JMP ACK ;send ACK 0412 SNDMSG: 0413 f998 86 b0 LDAA #$0B0 ;Minor node send 0414 f99a 9a 98 ORAA DEVNUM ;or in Node ID 0415 f99c bd fa 11 JSR TXBYTE ;send it 0416 f99f 25 30 BCS TXSTR1 ;if bad send 0417 f9a1 96 8a LDAA STRLEN ;get message length MSB 0418 f9a3 bd fa 11 JSR TXBYTE ;send it 0419 f9a6 25 29 BCS TXSTR1 ;if bad send 0420 f9a8 96 8b LDAA STRLEN+1 ;get message length LSB 0421 f9aa bd fa 11 JSR TXBYTE ;send it 0422 f9ad 25 22 BCS TXSTR1 ;if bad send 0423 f9af 7f 00 8e CLR CHKSUM ;clear checksum and fall through to send message 0424 TXSTR: 0425 f9b2 a6 00 LDAA $0,X ;get byte pointed to by IX 0426 f9b4 bd fa 11 JSR TXBYTE ;send it 0427 f9b7 25 18 BCS TXSTR1 ;jump if error 0428 f9b9 98 8e EORA CHKSUM ;generate checksum 0429 f9bb 97 8e STAA CHKSUM ;save it 0430 f9bd 08 INX ;increment pointer 0431 f9be dc 8a LDD STRLEN ;load DA with string length 0432 f9c0 83 00 01 SUBD #$1 ;decrement it 0433 f9c3 dd 8a STD STRLEN ;save string length 0434 f9c5 26 eb BNE TXSTR ;send more if leength > 0 0435 f9c7 96 8e LDAA CHKSUM ;get checksum 0436 f9c9 bd fa 11 JSR TXBYTE ;send it 0437 f9cc 25 03 BCS TXSTR1 ;if error 0438 f9ce bd fa 29 JSR RXBYTE ;get response 0439 TXSTR1: 0440 f9d1 39 RTS 0441 SCIEND: 0442 f9d2 7d 00 9e TST DATREQ ;test SCI status flag 0443 f9d5 27 0b BEQ SCIND1 ;if it's 0 exit, SCI routine 0444 f9d7 86 0a LDAA #$0A ;enable Rx & Tx, but disable interrupts 0445 f9d9 97 11 STAA SCICSR 0446 f9db 96 11 LDAA SCICSR ;read status to reset 0447 f9dd 96 12 LDAA SCIRXD ;read receive to reset 0448 f9df bd fa 29 JSR RXBYTE ;read byte from Net 0449 SCIND1: 0450 f9e2 3b RTI ;return from SCI interrupt 0451 GETSTAT: 0452 f9e3 96 95 LDAA SSTAT ;get contents of 95 in A 0453 f9e5 48 ASLA ;put in upper nibble 0454 f9e6 48 ASLA 0455 f9e7 48 ASLA 0456 f9e8 48 ASLA 0457 f9e9 9a 94 ORAA PSTAT ;put 94 in lower nibble 0458 f9eb 97 93 STAA CSTAT ;save in 93 0459 f9ed 39 RTS 0460 TBL2: 0461 f9ee 80 00 DW $8000 0462 TBL3: 0463 f9f0 04 01 DW $401 0464 f9f2 00 DB $0 0465 RDSCI: 0466 f9f3 0d SEC ;set carry flag 0467 f9f4 d6 11 LDAB SCICSR ;get SCI status in B 0468 f9f6 96 12 LDAA SCIRXD ;read SCI data 0469 f9f8 c4 40 ANDB #$40 ;check for read errors, carry not affected 0470 f9fa 27 03 BEQ RDSCI1 ;branch if no error 0471 f9fc 0c CLC ;clear the carry 0472 f9fd 0b SEV ;set overflow 0473 f9fe 39 RTS 0474 RDSCI1: 0475 f9ff d6 99 LDAB CMDSTG ;check if in middle of a command 0476 fa01 26 0c BNE RDSCI3 ;branch if so 0477 fa03 16 TAB ;transfer Node ID to B 0478 fa04 84 0f ANDA #$0F ;look at lower nibble of ID 0479 fa06 91 98 CMPA DEVNUM ;is it us 0480 fa08 26 04 BNE RDSCI2 ;jump if not 0481 fa0a 17 TBA ;put byte back in A 0482 fa0b 0d SEC ;set the carry 0483 fa0c 20 01 BRA RDSCI3 ;clear next 0484 RDSCI2: 0485 fa0e 0c CLC ;clear carry 0486 RDSCI3: 0487 fa0f 0a CLV ;clear overflow 0488 fa10 39 RTS 0489 TXBYTE: 0490 fa11 3c PSHX ;save IX 0491 fa12 ce 00 16 LDX #$16 ;store count for timeout 0492 TXBYT1: 0493 fa15 09 DEX ;decrement count 0494 fa16 27 0b BEQ TXBYT2 ;timeout if count exhausted 0495 fa18 d6 11 LDAB SCICSR ;get SCI status 0496 fa1a c4 20 ANDB #$20 ;is Tx register full 0497 fa1c 27 f7 BEQ TXBYT1 ;wait if it is 0498 fa1e 97 13 STAA SCITXD ;put byte in Tx register (send it) 0499 fa20 0c CLC ;clear the carry 0500 fa21 20 04 BRA TXBYT3 ;exit 0501 TXBYT2: 0502 fa23 bd fa 47 JSR SCIRES ;reset SCI 0503 fa26 0d SEC ;set the carry 0504 TXBYT3: 0505 fa27 38 PULX ;restore IX 0506 fa28 39 RTS 0507 RXBYTE: 0508 fa29 3c PSHX ;save IX 0509 fa2a ce 00 22 LDX #$22 ;count for timeout 0510 RXBYT1: 0511 fa2d 09 DEX ;decrement count 0512 fa2e 27 13 BEQ RXBYT3 ;timeout if count exhausted 0513 fa30 d6 11 LDAB SCICSR ;get SCI status 0514 fa32 c4 20 ANDB #$20 ;check if last byte transmitted yet 0515 fa34 27 f7 BEQ RXBYT1 ;wait until it is 0516 fa36 d6 12 LDAB SCIRXD ;read Rx data 0517 RXBYT2: 0518 fa38 09 DEX ;decrement counter 0519 fa39 27 08 BEQ RXBYT3 ;if timed out 0520 fa3b d6 11 LDAB SCICSR ;read SCI status 0521 fa3d 2a f9 BPL RXBYT2 ;loop if bit 7 is not set 0522 fa3f d6 12 LDAB SCIRXD ;read byte 0523 fa41 38 PULX ;restore IX 0524 fa42 39 RTS 0525 RXBYT3: 0526 fa43 8d 02 BSR SCIRES ;reset SCI 0527 fa45 38 PULX ;restore IX 0528 fa46 39 RTS 0529 SCIRES: 0530 fa47 d6 11 LDAB SCICSR ;read SCI status 0531 fa49 d6 12 LDAB SCIRXD ;clear any received data 0532 fa4b c6 1b LDAB #$1B ;enable Rx, Tx, Wakeup 0533 fa4d d7 11 STAB SCICSR 0534 fa4f c6 00 LDAB #$0 ;reset command stage to 0 0535 fa51 d7 99 STAB CMDSTG 0536 fa53 39 RTS 0537 SETREQ: 0538 fa54 24 06 BCC SETRQ1 ;if carry clear, ie if not called by reset command 0539 fa56 86 ff LDAA #$0FF ;put FF in DATREQ 0540 fa58 97 9e STAA DATREQ 0541 fa5a 20 0a BRA SETRQ2 ;return 0542 SETRQ1: 0543 fa5c 97 9f STAA RDWRT ;put's 0BH in RDWRT to force a read 0544 fa5e 86 aa LDAA #$0AA ;put AA in DATREQ 0545 fa60 97 9e STAA DATREQ 0546 fa62 86 0b LDAA #$0B ;disable receive interrupt 0547 fa64 97 11 STAA SCICSR 0548 SETRQ2: 0549 fa66 39 RTS 0550 ; 0551 ; Initialize Hard Disk routine 0552 ; 0553 RESET: 0554 fa67 0f SEI ;disable interrupts 0555 fa68 8e 00 e8 LDS #$0E8 ;set stack pointer to E8 0556 fa6b 86 00 LDAA #$00 ;set port 1 data direction to 00000000 0557 fa6d 97 00 STAA P1DDR ; (all inputs) 0558 fa6f 86 ff LDAA #$0FF ;set port 4 data direction to 11111111 0559 fa71 97 05 STAA P4DDR ; (all outputs) 0560 fa73 86 15 LDAA #$15 ;set port 2 data direction to 00010101 0561 fa75 97 01 STAA P2DDR ; (P20-P22 & P24 input, P25 output) 0562 fa77 86 04 LDAA #$4 ;set SCI rate & mode 62.5 kbaud, NRZ, 0563 ; internal clock, post2 bit 2 not used 0564 fa79 97 10 STAA RMCR 0565 fa7b 86 1b LDAA #$1B ;enable Rx, Tx, Wakeup 0566 fa7d 97 11 STAA SCICSR 0567 fa7f 86 ff LDAA #$0FF ;enable internal ram 0568 fa81 97 14 STAA RAMCR 0569 fa83 ce 00 ff LDX #$0FF ;start clearing memory at 0FFH 0570 RESET1: 0571 fa86 6f 00 CLR $0,X ;reset memory 0572 fa88 09 DEX ;decrement pointer 0573 fa89 8c 00 80 CPX #$80 ;is it 80H 0574 fa8c 24 f8 BCC RESET1 ;no, loop 0575 fa8e 7a 00 89 DEC LSTMSG+4 ;set lstmsg+4 to 0FFH 0576 ; 0577 ; Set device number (DRVNO or DRVNO+1) 0578 ; 0579 fa91 96 02 LDAA P1DATA ;read port 1 0580 fa93 84 80 ANDA #$80 ;is switch on back set to drive ID 2? 0581 fa95 0c CLC ;clear carry 0582 fa96 49 ROLA ;move bit 7 to bit 1 0583 fa97 49 ROLA 0584 fa98 8a 04 ORAA #DRVNO ;or in base drive ID 0585 fa9a 97 98 STAA DEVNUM ;save it 0586 ; 0587 ; Init hard drive 0588 ; 0589 fa9c bd fa f7 JSR TBUSY ;Wait for drive to become ready 0590 fa9f 86 04 LDAA #HRESET ;Set RESET bit in control register 0591 faa1 b7 18 0e STAA WRCONT 0592 faa4 01 NOP ;Wait 0593 faa5 01 NOP 0594 faa6 01 NOP 0595 faa7 01 NOP 0596 faa8 01 NOP 0597 faa9 01 NOP 0598 faaa 01 NOP 0599 faab 01 NOP 0600 faac 01 NOP 0601 faad 01 NOP 0602 faae 86 02 LDAA #HNOIRQ ;Clear RESET bit and 0603 fab0 b7 18 0e STAA WRCONT ; Turn off hard disk interrupt 0604 fab3 bd fa f7 JSR TBUSY ;Wait for drive to complete action 0605 fab6 86 10 LDAA #HRECAL ;Home drive 0606 fab8 b7 18 07 STAA WRCMD 0607 fabb bd fa f7 JSR TBUSY ;Wait for drive to home 0608 ; 0609 fabe bd fb 01 JSR GETPARM ;Go get HD parameters 0610 ; 0611 ; Set Hard Disk parameters 0612 ; 0613 fac1 4f CLRA ;Zero MSB of HNHSPT and HSPT 0614 fac2 f6 14 06 LDAB PSPT ;Get no of HD sectors per track 0615 fac5 dd a1 STD HSPT ;Save for later use here 0616 fac7 f7 18 02 STAB WRSECCT ;Send to controller for STPARM 0617 faca f6 14 07 LDAB PNHSPT ;Get LSB of no of HDs x SPT 0618 facd dd a3 STD HNHSPT ;Save word for later use here 0619 facf fc 14 03 LDD PTRACK ;Get no of HD cylinders 0620 fad2 b7 18 04 STAA WRCYLLO ;Send to controller for STPARM 0621 fad5 f7 18 05 STAB WRCYLHI 0622 fad8 b6 14 05 LDAA PSEEK ;Get No of heads (stored in PSEEK) 0623 fadb 84 0f ANDA #$0F ;Get rid of upper nibble 0624 fadd 8a a0 ORAA #$0A0 ;Always select drive 1 0625 fadf b7 18 06 STAA WRSDH ;Send to controller for STPARM 0626 fae2 86 91 LDAA #HSTPARM ;Send Set Parameters command to HD 0627 fae4 b7 18 07 STAA WRCMD 0628 fae7 bd fa f7 JSR TBUSY ;Wait for drive to finish operation 0629 faea b6 08 07 LDAA RDSTAT ;Get drive status 0630 faed 84 01 ANDA #$1 ;Mask out ERROR bit 0631 faef 27 03 BEQ RESET2 ;Good, continue 0632 faf1 7e fc 55 JMP MISMED ;No good, go report 0633 RESET2: 0634 faf4 7e fc 74 JMP DSKRES ;Go enable interrupts for Adamnet 0635 ; and jump to MAIN when finished 0636 ; 0637 ; Wait until current hard disk operation is complete 0638 ; 0639 TBUSY: 0640 faf7 b6 08 07 LDAA RDSTAT ;Get contents of Status register 0641 fafa 88 50 EORA #$50H ;Invert RDY and SC bits (6 & 4) 0642 fafc 84 d2 ANDA #$0D2H ;Look only at BSY, \RDY, \SC & IDX bits 0643 fafe 26 f7 BNE TBUSY ;Loop if any are set (high) 0644 fb00 39 RTS ;Return when all are clear (low) 0645 ; 0646 ; Get Hard Disk parameters 0647 ; 0648 GETPARM: 0649 fb01 4f CLRA 0650 fb02 b7 18 04 STAA WRCYLLO ;Set cylinder = 0 0651 fb05 b7 18 05 STAA WRCYLHI 0652 fb08 4c INCA 0653 fb09 b7 18 03 STAA WRSECNO ;Set sector = 1 0654 fb0c b7 18 02 STAA WRSECCT ;Get one sector 0655 fb0f 86 a0 LDAA #$A0 ;Select HD0, Head 0 0656 fb11 b7 18 06 STAA WRSDH 0657 ; 0658 ; Get Hard Disk parameters 0659 ; 0660 fb14 86 20 LDAA #HREAD 0661 fb16 b7 18 07 STAA WRCMD ;Send read command to drive 0662 fb19 bd fa f7 JSR TBUSY ;Wait for drive to finish 0663 fb1c b6 08 07 LDAA RDSTAT ;Get drive status 0664 fb1f 84 01 ANDA #$1 ;Mask out ERROR bit 0665 fb21 27 03 BEQ GTPARM2 ;Good, continue 0666 fb23 7e fc 65 JMP CRC ;No good, go report 0667 GTPARM2: 0668 fb26 ce 04 00 LDX #BLKWRT ;Good, Point at Write Buffer 0669 fb29 4f CLRA ;Zero word counter 0670 GTPARM3: 0671 fb2a f6 08 08 LDAB RDDATLO ;Get sector data (512 bytes) 0672 fb2d e7 00 STAB 0,X ;Get lower byte & store in buffer 0673 fb2f 08 INX ;Point at next buffer location 0674 fb30 f6 08 09 LDAB RDDATHI ;Get upper byte 0675 fb33 e7 00 STAB 0,X ;Store in buffer 0676 fb35 08 INX ;Point at next buffer location 0677 fb36 4a DECA ;Decrement word counter 0678 fb37 26 f1 BNE GTPARM3 ;More words left; get next one 0679 fb39 39 RTS ;Finished, return to calling pgm 0680 ; 0681 ; Loop here waiting for ADAMnet data I/O request from 0682 ; ADAMnet interrupt handler 0683 ; 0684 MAIN: 0685 fb3a 96 9e LDAA DATREQ ;is there a data request 0686 fb3c 27 fc BEQ MAIN ;no, return to start of main loop 0687 fb3e 81 ff CMPA #$0FFH ;yes, is it a reset drive request? 0688 fb40 26 03 BNE MAIN1 ;no, continue 0689 fb42 7e fa 67 JMP RESET ;yes, go reset drive 0690 MAIN1: 0691 fb45 d6 84 LDAB CURMSG+4 ;is the primary device requested? 0692 fb47 27 05 BEQ DODATA ;yes, skip next 0693 fb49 7f 00 9e CLR DATREQ ;clear data request 0694 fb4c 20 ec BRA MAIN ;loop some more 0695 0696 DODATA: 0697 fb4e 0f SEI ;disable interrupts 0698 fb4f 96 9f LDAA RDWRT ;test read/write flag 0699 fb51 81 0c CMPA #$0C ;is it write? 0700 fb53 26 27 BNE RDBLK ;no, go do read 0701 fb55 de 80 LDX CURMSG ;yes, get requested block 0702 fb57 8c 53 ca CPX #$53CA ;is it a CA53 request? 0703 fb5a 26 02 BNE CHKFMT ;no, check if it is format 0704 fb5c 20 18 BRA NOTFMT ;yes, skip next 0705 CHKFMT: 0706 fb5e 8c ce fa CPX #$0CEFA ;is it format = FACEH 0707 fb61 27 03 BEQ CHKFMT2 ;yes, go finish 0708 fb63 7e fb ee JMP WRBLK ;no, go write block 0709 CHKFMT2: 0710 fb66 86 ff LDAA #$0FF ;yes, set all message bytes to 0FFH 0711 fb68 c6 ff LDAB #$0FF 0712 fb6a dd 85 STD LSTMSG 0713 fb6c dd 87 STD LSTMSG+2 0714 fb6e 97 89 STAA LSTMSG+4 0715 fb70 dd 80 STD CURMSG 0716 fb72 dd 80 STD CURMSG ;should be +2 ####### 0717 fb74 97 80 STAA CURMSG ; and +4 0718 NOTFMT: 0719 fb76 7f 00 9e CLR DATREQ ;clear data request flag 0720 fb79 7e fc 52 JMP OKRDWR ;finish up with no error 0721 ; 0722 ; Read a block (2 sectors - 1024 bytes) from disk 0723 ; 0724 RDBLK: 0725 fb7c bd fa f7 JSR TBUSY ;Wait until controller ready 0726 fb7f bd fc 7f JSR CLCCHS ;Go calculate Cyl, Hd, Sector 0727 ; and send them to hard drive 0728 fb82 86 20 LDAA #HREAD ;Go get first sector 0729 fb84 b7 18 07 STAA WRCMD ;Send read command to drive 0730 fb87 bd fa f7 JSR TBUSY ;Wait for drive to finish 0731 fb8a b6 08 07 LDAA RDSTAT ;Get drive status 0732 fb8d 84 01 ANDA #$1 ;Mask out ERROR bit 0733 fb8f 27 03 BEQ RDBLK0 ;Good, continue 0734 fb91 7e fc 69 JMP MISBLK ;No good, go report 0735 RDBLK0: 0736 fb94 b6 08 07 LDAA RDSTAT ;Good, get HD controller status 0737 fb97 84 08 ANDA #$8 ;Mask out DRQ bit, 1 = send data 0738 fb99 27 f9 BEQ RDBLK0 ;Wait for drive to request data 0739 fb9b ce 04 00 LDX #BLKWRT ;OK, point at Write Buffer 0740 fb9e 4f CLRA ;Zero word counter 0741 RDBLK1: 0742 fb9f f6 08 08 LDAB RDDATLO ;First 256 words (512 bytes) 0743 fba2 e7 00 STAB 0,X ;Get lower byte & store in buffer 0744 fba4 08 INX ;Point at next buffer location 0745 fba5 f6 08 09 LDAB RDDATHI ;Get upper byte 0746 fba8 e7 00 STAB 0,X ;Store in buffer 0747 fbaa 08 INX ;Point at next buffer location 0748 fbab 4a DECA ;Decrement word counter 0749 fbac 26 f1 BNE RDBLK1 ;More words left; get next one 0750 ; 0751 ; Get Second Sector 0752 ; 0753 fbae bd fa f7 JSR TBUSY ;Wait until controller ready 0754 fbb1 bd fc cd JSR CLCNXT ;Done, Calculate next Cyl, Hd, Sec 0755 ; and send them to hard drive 0756 fbb4 86 20 LDAA #HREAD ;Send read command to drive 0757 fbb6 b7 18 07 STAA WRCMD 0758 fbb9 bd fa f7 JSR TBUSY ;Wait for drive to finish 0759 fbbc b6 08 07 LDAA RDSTAT ;Get drive status 0760 fbbf 84 01 ANDA #$1 ;Mask out ERROR bit 0761 fbc1 27 03 BEQ RDBLK2 ;Good, continue 0762 fbc3 7e fc 69 JMP MISBLK ;NG, go report missing block 0763 RDBLK2: 0764 fbc6 b6 08 07 LDAA RDSTAT ;Good, get HD controller status 0765 fbc9 84 08 ANDA #$8 ;Mask out DRQ bit, 1 = send data 0766 fbcb 27 f9 BEQ RDBLK2 ;Wait for drive to request data 0767 fbcd ce 06 00 LDX #BLKWRT+512 ;OK, point at second half of buffer 0768 fbd0 4f CLRA ;Zero word counter 0769 RDBLK3: 0770 fbd1 f6 08 08 LDAB RDDATLO ;Second 256 words (512 bytes) 0771 fbd4 e7 00 STAB 0,X ;Get lower byte & store in buffer 0772 fbd6 08 INX ;Point at next buffer location 0773 fbd7 f6 08 09 LDAB RDDATHI ;Get upper byte 0774 fbda e7 00 STAB 0,X ;Store in buffer 0775 fbdc 08 INX ;Point at next buffer location 0776 fbdd 4a DECA ;Decrement word counter 0777 fbde 26 f1 BNE RDBLK3 ;More words left; get next one 0778 RDBLK4: ;Finished, wrap up 0779 fbe0 dc 80 LDD CURMSG ;Transfer current message to 0780 fbe2 dd 85 STD LSTMSG ; last message 0781 fbe4 dc 82 LDD CURMSG+2 0782 fbe6 dd 87 STD LSTMSG+2 0783 fbe8 96 84 LDAA CURMSG+4 0784 fbea 97 89 STAA LSTMSG+4 0785 fbec 20 64 BRA OKRDWR ;finish up, no error 0786 ; 0787 ; Write a block (2 sectors - 1024 bytes) to disk 0788 ; 0789 WRBLK: ;Send first sector 0790 fbee bd fa f7 JSR TBUSY ;Wait until controller ready 0791 fbf1 bd fc 7f JSR CLCCHS ;Go Calculate Cyl, Hd, Sector 0792 ; and send them to the drive 0793 fbf4 86 30 LDAA #HWRITE ;Send write command to drive 0794 fbf6 b7 18 07 STAA WRCMD 0795 fbf9 bd fa f7 JSR TBUSY ;Wait for drive to finish 0796 fbfc b6 08 07 LDAA RDSTAT ;Get drive status 0797 fbff 84 01 ANDA #$1 ;Mask out ERROR bit 0798 fc01 26 66 BNE MISBLK ;No good, go report 0799 WRBLK0: 0800 fc03 b6 08 07 LDAA RDSTAT ;Good, get HD controller status 0801 fc06 84 08 ANDA #$8 ;Mask out DRQ bit, 1 = send data 0802 fc08 27 f9 BEQ WRBLK0 ;Wait for drive to request data 0803 fc0a ce 14 00 LDX #BLKRD ;OK, Point at Read Buffer 0804 fc0d 4f CLRA ;Zero word counter 0805 fc0e 08 INX ;Point at high byte 0806 WRBLK1: 0807 fc0f e6 00 LDAB 0,X ;Get high byte 0808 fc11 f7 18 09 STAB WRDATHI ;Send it to drive 0809 fc14 09 DEX ;Point at low byte 0810 fc15 e6 00 LDAB 0,X ;Get low byte 0811 fc17 f7 18 08 STAB WRDATLO ;Send it to drive 0812 fc1a 08 INX ;Point back at high byte 0813 fc1b 08 INX ;Point to next low byte 0814 fc1c 08 INX ;Point to next high byte 0815 fc1d 4a DECA ;Decrement word count 0816 fc1e 26 ef BNE WRBLK1 ;More words, go send them 0817 WRBLK2: ;Send second sector 0818 fc20 bd fa f7 JSR TBUSY ;Wait until controller ready 0819 fc23 bd fc cd JSR CLCNXT ;Done, calculate next Cyl, Hd, 0820 ; Sector and send to the drive 0821 fc26 86 30 LDAA #HWRITE ;Send write command to drive 0822 fc28 b7 18 07 STAA WRCMD 0823 fc2b bd fa f7 JSR TBUSY ;Wait for drive to finish 0824 fc2e b6 08 07 LDAA RDSTAT ;Get drive status 0825 fc31 84 01 ANDA #$1 ;Mask out ERROR bit 0826 fc33 26 34 BNE MISBLK ;No good, go report 0827 WRBLK3: 0828 fc35 b6 08 07 LDAA RDSTAT ;Good, get HD controller status 0829 fc38 84 08 ANDA #$8 ;Mask out DRQ bit, 1 = send data 0830 fc3a 27 f9 BEQ WRBLK3 ;Wait for drive to request data 0831 fc3c ce 16 00 LDX #BLKRD+512 ;Good, point @ 2nd half of Rd Buff 0832 fc3f 4f CLRA ;Zero word counter 0833 fc40 08 INX ;Point at high byte 0834 WRBLK4: 0835 fc41 e6 00 LDAB 0,X ;Get high byte 0836 fc43 f7 18 09 STAB WRDATHI ;Send it to drive 0837 fc46 09 DEX ;Point at low byte 0838 fc47 e6 00 LDAB 0,X ;Get low byte 0839 fc49 f7 18 08 STAB WRDATLO ;Send it to drive 0840 fc4c 08 INX ;Point back at high byte 0841 fc4d 08 INX ;Point to next low byte 0842 fc4e 08 INX ;Point to next high byte 0843 fc4f 4a DECA ;Decrement word count 0844 fc50 26 ef BNE WRBLK4 ;More words, go send them 0845 ; 0846 ; Read/Write clean-up routines 0847 ; 0848 OKRDWR: 0849 fc52 4f CLRA ;no error so clear A 0850 fc53 20 16 BRA DSKDN 0851 MISMED: 0852 fc55 dc 80 LDD CURMSG ;transfer current message to last message 0853 fc57 dd 85 STD LSTMSG 0854 fc59 dc 82 LDD CURMSG+2 0855 fc5b dd 87 STD LSTMSG+2 0856 fc5d 96 84 LDAA CURMSG+4 0857 fc5f 97 89 STAA LSTMSG+4 0858 fc61 86 03 LDAA #$3 ;status = missing media 0859 fc63 20 06 BRA DSKDN 0860 CRC: 0861 fc65 86 01 LDAA #$1 ;status = CRC error 0862 fc67 20 02 BRA DSKDN 0863 MISBLK: 0864 fc69 86 02 LDAA #$2 ;status = missing block error 0865 DSKDN: 0866 fc6b 97 94 STAA PSTAT 0867 fc6d 20 02 BRA DSKDN1 0868 ; 0869 fc6f 97 95 STAA SSTAT ;unused code for secondary device 0870 DSKDN1: 0871 fc71 7f 00 9e CLR DATREQ 0872 DSKRES: 0873 fc74 86 1b LDAA #$1B ;enable Tx, Rx, Wakeup 0874 fc76 97 11 STAA SCICSR 0875 fc78 4f CLRA 0876 fc79 97 99 STAA CMDSTG ;reset command stage 0877 fc7b 0e CLI ;enable interrupts 0878 fc7c 7e fb 3a JMP MAIN ;wait loop 0879 ; 0880 ; Calculate Cylinder, Sector and Head from Block Number 0881 ; 0882 CLCCHS: 0883 fc7f d6 80 LDAB CURMSG ;Get ADAMnet block number into 0884 fc81 96 81 LDAA CURMSG+1 ; Accumulators for double byte math 0885 fc83 7f 00 a0 CLR THREEB ;Assume 2 byte SEC# (THREEB = 0) 0886 fc86 05 LSLD ;Multiply X2 for 512 byte sectors 0887 fc87 24 03 BCC CLCHS1 ;Skip next if SEC# < 64K (2 bytes) 0888 fc89 7a 00 a0 DEC THREEB ;3 byte SEC#, set #BYTE = FF 0889 CLCHS1: 0890 fc8c ce ff ff LDX #$0FFFFH ;Initialize Index Register (will 0891 fc8f 7f 00 a5 CLR REQHD ; hold REQCYL) and Head storage 0892 fc92 7a 00 a5 DEC REQHD ; location for math 0893 CLCHS2: 0894 fc95 93 a3 SUBD HNHSPT ;Divide REQBLK by SEC*HDS until 0895 fc97 08 INX ; overflow, # of passes thru loop 0896 fc98 24 fb BCC CLCHS2 ; provides CYL number in Index Reg 0897 fc9a 7d 00 a0 TST THREEB ;See if have 2 or 3 byte sec # 0898 fc9d 27 05 BEQ CLCHS3 ;2 byte, done with SECHDS divide 0899 fc9f 7f 00 a0 CLR THREEB 0900 fca2 20 f1 BRA CLCHS2 ;3 byte, continue SECHDS divide 0901 CLCHS3: ;D has remainder, X has REQCYL# 0902 fca4 3c PSHX ;Save REQCYL# 0903 fca5 d3 a3 ADDD HNHSPT ;Add back last subtraction 0904 CLCHS4: 0905 fca7 93 a1 SUBD HSPT ;Divide remainder by Sec/Trk until 0906 fca9 7c 00 a5 INC REQHD ; overflow, # passes thru loop 0907 fcac 24 f9 BCC CLCHS4 ; provides HD # in REQHD 0908 fcae d3 a1 ADDD HSPT ;Add back last subtraction 0909 fcb0 5c INCB ;Add one sector for number conversion 0910 fcb1 d7 a6 STAB REQSEC ;Remainder is SEC#, save for later use 0911 fcb3 f7 18 03 STAB WRSECNO ;Send it to the drive 0912 fcb6 32 PULA ;Get REQCYL# back 0913 fcb7 33 PULB ; - LSB in B, MSB in A 0914 fcb8 dd a7 STD REQCYL ;Save for later use 0915 fcba f7 18 04 STAB WRCYLLO ;Send REQCYL# LSB to drive 0916 fcbd b7 18 05 STAA WRCYLHI ;Send REQCYL# MSB to drive 0917 fcc0 86 01 LDAA #$1 ;Set up for single sector access 0918 fcc2 b7 18 02 STAA WRSECCT ;Set drive sector count to 1 0919 fcc5 96 a5 LDAA REQHD ;Get Head # to access 0920 fcc7 8a a0 ORAA #$A0 ;Select HD0 0921 fcc9 b7 18 06 STAA WRSDH ;Send to drive 0922 fccc 39 RTS ;Return to calling program 0923 ; 0924 ; Calculate second sector's address (Cyl, Hd, Sec) 0925 ; 0926 CLCNXT: 0927 0928 ; Set SECCT to 1 before anything else? 0929 ; Do I have the order right? SEC -> HD -> CYL? 0930 0931 fccd 86 01 LDAA #1 0932 fccf b7 18 02 STAA WRSECCT ;One sector transfer 0933 fcd2 96 a6 LDAA REQSEC ;Get requested sector back 0934 fcd4 4c INCA ;Point at next sector 0935 fcd5 91 a2 CMPA HSPT+1 ;See if greater than Max Sec# 0936 fcd7 2e 06 BGT CLCNXT1 ;Yes, go correct HD# 0937 fcd9 97 a6 STAA REQSEC ;No, okay as is - save it 0938 fcdb b7 18 03 STAA WRSECNO ;Write it to the hard disk 0939 fcde 39 RTS ;Finished 0940 CLCNXT1: 0941 fcdf 86 01 LDAA #1 ;Start at beginning of next trk 0942 fce1 97 a6 STAA REQSEC ;Save it for later use 0943 fce3 b7 18 03 STAA WRSECNO ;Write it to the hard disk 0944 fce6 96 a5 LDAA REQHD ;Get back last head number 0945 fce8 4c INCA ;Increment it 0946 fce9 b1 14 05 CMPA PSEEK ;See if greater than #HDs 0947 fcec 2e 06 BGT CLCNXT2 ;Yes, go correct CYL# 0948 fcee 8a a0 ORAA #$A0 ;No, mask in HD0 select 0949 fcf0 b7 18 06 STAA WRSDH ;Send to hard disk 0950 fcf3 39 RTS ;Finished 0951 CLCNXT2: 0952 fcf4 7f 00 a5 CLR REQHD ;Start at first head 0953 fcf7 86 a0 LDAA #$A0 ;Send first head # to HD 0954 fcf9 b7 18 06 STAA WRSDH 0955 fcfc dc a7 LDD REQCYL ;Get previous CYL# to modify 0956 fcfe c3 00 01 ADDD #1 ;Increment to next Cylinder 0957 fd01 dd a7 STD REQCYL ;Save it back again 0958 fd03 f7 18 04 STAB WRCYLLO ;Write it to the hard disk 0959 fd06 b7 18 05 STAA WRCYLHI 0960 fd09 39 RTS ;Finished 0961 ; 0962 ; Interrupt vectors 0963 ; 0964 ffef ORG 0FFEFH 0965 0966 RETI: 0967 ffef 3b RTI ;return from interrupt 0968 fff0 f8 01 DW SCIINT ;IRQ2/SCI (RDRF,ORFE,TDRE) 0969 fff2 ff ef DW RETI ;IRQ2/Timer overflow 0970 fff4 ff ef DW RETI ;IRQ2/Timer output compare 0971 fff6 ff ef DW RETI ;IRQ2/Timer input capture 0972 fff8 ff ef DW RETI ;IRQ1 interrupt (IRQ1 - IS3) 0973 fffa ff ef DW RETI ;software interrupt (SWI) 0974 fffc ff ef DW RETI ;Non-maskable Interrupt 0975 fffe fa 67 DW RESET ;reset 0976 END Number of errors 0